package com.degani.pdf;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import com.itextpdf.text.pdf.AcroFields;
import com.itextpdf.text.pdf.PdfReader;

public class PDFExtractor {

	private static Logger logger = Logger.getLogger(PDFExtractor.class);	
	
	public static void printAllFields(String path) throws IOException {
	    PdfReader pdfReader = new PdfReader(path);
	    AcroFields acroFields = pdfReader.getAcroFields();
	    Map<String,AcroFields.Item> fields = acroFields.getFields();
	    for(String name : fields.keySet()){
	    	System.out.println(name + ":" + acroFields.getField(name));
	    }
	}
	
	public static String getFormField(String pdfPath, String formField){
		try{
	    PdfReader pdfReader = new PdfReader(pdfPath);
	    AcroFields acroFields = pdfReader.getAcroFields();
	    return acroFields.getField(formField);
		} catch(IOException e){
			logger.error(String.format("Could not read %s in %s", 
					formField, pdfPath), e);
			return "Error - See application.log";
		}
	}
	
	/*public static void fillOutSpreadsheet(String name) throws IOException{
		// open the spreadsheet
		Workbook template = new XSSFWorkbook(new FileInputStream("./templates/Financial Plan Input 24 March 2012.xlsx"));

		Sheet s = template.getSheet("Input");
		Cell c = s.getRow(6).getCell(3);
		c.setCellValue(name);
		FileOutputStream out = new FileOutputStream("./templates/out.xlsx");
		template.write(out);
		out.close();
	}*/

	public static void process(List<String> inputPdfs, 
			String excelTemplate, FieldMap mappings, 
			String outputFolder, Progress p) 
					throws FileNotFoundException, IOException{
		int sections = inputPdfs.size();
		double progress = 0.0f;
		double increment = 1.0 / (double)sections;
		
		for(int i = 0 ; i < inputPdfs.size(); i++){
			
			p.setProgress((int)progress);
			p.setStatusMessage(String.format("Processing PDF %d of %d", i+1, inputPdfs.size()));
			try{
				// TODO: set the "PROCESSING" flag on the table
				applyTemplate(inputPdfs.get(i), excelTemplate, mappings, outputFolder);
			} catch(Exception e){
				logger.error(String.format("Error while processing: %s", inputPdfs.get(i)),e);
				// TODO: set the "ERROR" flag on the table
			}
			progress += increment;
		}
		p.setProgress(100);
	}
	
	public static void applyTemplate(String pdf, String template, 
			FieldMap mappings, String outputFolder) throws IOException{
		Workbook workbook = new XSSFWorkbook(new FileInputStream(template));
		PdfReader pdfReader = new PdfReader(pdf);
	    AcroFields acroFields = pdfReader.getAcroFields();
	    for(String formField : mappings.keySet()){
	    	String value = acroFields.getField(formField);
	    	if(value == null){
	    		value = "";
	    	}
	    	String excelDest = mappings.get(formField);
	    	if(excelDest != null && !"".equals(excelDest)){
		    	String[] split = excelDest.split("!");
		    	if(split.length!=2){
		    		logger.error("Could not understand mapping field: " + excelDest);
		    	} else {
		    		String sheetName = split[0];
		    		String address = split[1];
		    		// get the sheet reference
		    		Sheet sheet = workbook.getSheet(sheetName);
		    		// convert the string address to a cell coordinate
		    		CellCoordinate coord = CellCoordinate.fromString(address);
		    		// set the value
		    		Cell cell = sheet.getRow(coord.getRow()).getCell(coord.getColumn());
		    		if(cell == null){
		    			logger.error(String.format("Could not find cell: %s", address));
		    		} else {
		    			cell.setCellValue(value);
		    		}
		    	}
	    	} else {
	    		logger.error(String.format("Could not understand mapping for form field: %s", formField));
	    	}
	    }
		FileOutputStream out = new FileOutputStream(getOutputFile(
				outputFolder, new File(pdf).getName(), acroFields.getField("Name")));
		workbook.write(out);
		out.close();
	}
	
	private static File getOutputFile(String outputFolder, String pdfName, String suffix){
		String noExt = pdfName.substring(0, pdfName.lastIndexOf('.'));
		File outputPath = new File(outputFolder);
		File f;
		int copy = 0;
		do{
			String fileName =  String.format("%s%s%s.xlsx", noExt, 
					suffix == null || "".equals(suffix) ? "" : "-" + suffix, 
					copy > 0 ? "-" + copy : "");
			f = new File(outputPath, fileName);
			copy++;
		}while(f.exists());
		return f;
	}
	
	public static void main(String[] args) {
		try {
			printAllFields("pdf/Planancial-Startup-Master-2-form-dist_distributed-filled out.pdf");
			//fillOutSpreadsheet("Ismail Degani;");
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
